home *** CD-ROM | disk | FTP | other *** search
/ X User Tools / X User Tools (O'Reilly and Associates)(1994).ISO / sources / xload / get_load.c < prev    next >
C/C++ Source or Header  |  1994-09-27  |  18KB  |  725 lines

  1. /*
  2.  * get_load - get system load
  3.  *
  4.  * $XConsortium: get_load.c,v 1.26 91/07/25 14:20:25 rws Exp $
  5.  *
  6.  * Copyright 1989 Massachusetts Institute of Technology
  7.  *
  8.  * Permission to use, copy, modify, distribute, and sell this software and its
  9.  * documentation for any purpose is hereby granted without fee, provided that
  10.  * the above copyright notice appear in all copies and that both that
  11.  * copyright notice and this permission notice appear in supporting
  12.  * documentation, and that the name of M.I.T. not be used in advertising or
  13.  * publicity pertaining to distribution of the software without specific,
  14.  * written prior permission.  M.I.T. makes no representations about the
  15.  * suitability of this software for any purpose.  It is provided "as is"
  16.  * without express or implied warranty.
  17.  *
  18.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  19.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  20.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  21.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  22.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  23.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25.  * Authors:  Many and varied...
  26.  *
  27.  * Call InitLoadPoint() to initialize.
  28.  * GetLoadPoint() is a callback for the StripChart widget.
  29.  */
  30.  
  31. #include <X11/Xos.h>
  32. #include <X11/Intrinsic.h>
  33. #include <stdio.h>
  34.  
  35. #ifdef att
  36. #define LOADSTUB
  37. #endif
  38.  
  39. #ifndef macII
  40. #ifndef apollo
  41. #ifndef LOADSTUB
  42. #include <nlist.h>
  43. #endif /* LOADSTUB */
  44. #endif /* apollo */
  45. #endif /* macII */
  46.  
  47. #if defined(MOTOROLA) && defined(SYSV)
  48. #include <sys/sysinfo.h>
  49. #endif
  50.  
  51. #ifdef sun
  52. #    include <sys/param.h>
  53. #    ifdef i386
  54. #        include <kvm.h>
  55. #        define    KVM_ROUTINES
  56. #    endif /* i386 */
  57. #endif
  58.  
  59. #if defined(umips) || (defined(ultrix) && defined(mips))
  60. #include <sys/fixpoint.h>
  61. #endif
  62.  
  63. #if  defined(CRAY) || defined(AIXV3)
  64. #include <sys/param.h>
  65. #define word word_t
  66. #include <sys/sysinfo.h>
  67. #undef word
  68. #undef n_type
  69. #define n_type n_value
  70. #endif    /* CRAY */
  71.  
  72. #ifdef sequent
  73. #include <sys/vm.h>
  74. #endif /* sequent */
  75.  
  76. #ifdef macII
  77. #include <a.out.h>
  78. #include <sys/var.h>
  79. #define X_AVENRUN 0
  80. #define fxtod(i) (vec[i].high+(vec[i].low/65536.0))
  81. struct lavnum {
  82.     unsigned short high;
  83.     unsigned short low;
  84. };
  85. #endif /* macII */
  86.  
  87. #ifdef hcx
  88. #include <sys/param.h>
  89. #endif /* hcx */
  90.  
  91. #if defined(UTEK) || defined(alliant) || (defined(MOTOROLA) && defined(SVR4))
  92. #define FSCALE    100.0
  93. #endif
  94.  
  95. #ifdef sequent
  96. #define FSCALE    1000.0
  97. #endif
  98.  
  99. #ifdef sgi
  100. #define FSCALE    1024.0
  101. #endif
  102.  
  103. #if defined(sony) && OSMAJORVERSION == 4
  104. #ifdef mips
  105. #include <sys/fixpoint.h>
  106. #else
  107. #include <sys/param.h>
  108. #endif
  109. #endif
  110.  
  111. #ifdef SVR4
  112. #ifndef FSCALE
  113. #define FSCALE    (1 << 8)
  114. #endif
  115. #endif
  116.  
  117. #ifdef X_NOT_POSIX
  118. extern long lseek();
  119. #endif
  120. extern void exit();
  121.  
  122. static xload_error();
  123.  
  124.  
  125. #ifdef apollo
  126. #include <apollo/base.h>
  127. #include <apollo/time.h>
  128. typedef struct {
  129.     short        state;        /* ready, waiting, etc. */
  130.     pinteger    usr;        /* user sr */
  131.     linteger    upc;        /* user pc */
  132.     linteger    usp;        /* user stack pointer */
  133.     linteger    usb;        /* user sb ptr (A6) */
  134.     time_$clock_t    cpu_total;    /* cumulative cpu used by process */
  135.     unsigned short    priority;    /* process priority */
  136.     } proc1_$info_t;
  137.  
  138. void proc1_$get_cput(
  139.     time_$clock_t    *cput
  140. );
  141.  
  142. void proc1_$get_info(
  143.     short        &pid,
  144.     proc1_$info_t    *info,
  145.     status_$t    *sts
  146. );
  147.  
  148. static int     lastNullCpu;
  149. static int     lastClock;
  150.  
  151. void InitLoadPoint()                /* Apollo version */
  152. {
  153.      time_$clock_t  timeNow;
  154.      proc1_$info_t  info;
  155.      status_$t      st;
  156.  
  157.      proc1_$get_info( (short) 2, &info, &st );
  158.      time_$clock( &timeNow );
  159.  
  160.      lastClock = timeNow.low32;
  161.      lastNullCpu = info.cpu_total.low32;
  162. }
  163.  
  164. /* ARGSUSED */
  165. void GetLoadPoint( w, closure, call_data )     /* Apollo version */
  166.      Widget    w;        /* unused */
  167.      caddr_t    closure;    /* unused */
  168.      caddr_t    call_data;    /* pointer to (double) return value */
  169. {
  170.      time_$clock_t  timeNow;
  171.      double         temp;
  172.      proc1_$info_t  info;
  173.      status_$t      st;
  174.  
  175.      proc1_$get_info( (short) 2, &info, &st );
  176.      time_$clock( &timeNow );
  177.  
  178.      temp = info.cpu_total.low32 - lastNullCpu;
  179.      *(double *)call_data = 1.0 - temp / (timeNow.low32 - lastClock);
  180.  
  181.      lastClock = timeNow.low32;
  182.      lastNullCpu = info.cpu_total.low32;
  183. }
  184. #else /* not apollo */
  185. #if defined(SYSV) && defined(SYSV386)
  186. /*
  187.  * inspired by 'avgload' by John F. Haugh II
  188.  */
  189. #include <sys/param.h>
  190. #include <sys/buf.h>
  191. #include <sys/immu.h>
  192. #include <sys/region.h>
  193. #include <sys/var.h>
  194. #include <sys/proc.h>
  195. #define KERNEL_FILE "/unix"
  196. #define KMEM_FILE "/dev/kmem"
  197. #define VAR_NAME "v"
  198. #define PROC_NAME "proc"
  199. #define BUF_NAME "buf"
  200. #define DECAY 0.8
  201. struct nlist namelist[] = {
  202.   {VAR_NAME},
  203.   {PROC_NAME},
  204.   {BUF_NAME},
  205.   {0},
  206. };
  207.  
  208. static int kmem;
  209. static struct var v;
  210. static struct proc *p;
  211. static caddr_t first_buf, last_buf;
  212.  
  213. void InitLoadPoint()                /* SYSV386 version */
  214. {
  215.     int i;
  216.  
  217.     nlist( KERNEL_FILE, namelist);
  218.  
  219.     for (i=0; namelist[i].n_name; i++) 
  220.     if (namelist[i].n_value == 0)
  221.         xload_error("cannot get name list from", KERNEL_FILE);
  222.  
  223.     if ((kmem = open(KMEM_FILE, O_RDONLY)) < 0)
  224.     xload_error("cannot open", KMEM_FILE);
  225.  
  226.     if (lseek(kmem, namelist[0].n_value, 0) == -1)
  227.     xload_error("cannot seek", VAR_NAME);
  228.  
  229.     if (read(kmem, &v, sizeof(v)) != sizeof(v))
  230.     xload_error("cannot read", VAR_NAME);
  231.  
  232.     if ((p=(struct proc *)malloc(v.v_proc*sizeof(*p))) == NULL)
  233.     xload_error("cannot allocat space for", PROC_NAME);
  234.       
  235.     first_buf = (caddr_t) namelist[2].n_value;
  236.     last_buf  = first_buf + v.v_buf * sizeof(struct buf);
  237. }
  238.     
  239. /* ARGSUSED */
  240. void GetLoadPoint( w, closure, call_data )    /* SYSV386 version */
  241. Widget    w;        /* unused */
  242. caddr_t    closure;    /* unused */
  243. caddr_t    call_data;    /* pointer to (double) return value */
  244. {
  245.     double *loadavg = (double *)call_data;
  246.     static double avenrun = 0.0;
  247.     int i, nproc, size;
  248.     
  249.     (void) lseek(kmem, namelist[0].n_value, 0);
  250.     (void) read(kmem, &v, sizeof(v));
  251.  
  252.     size = (struct proc *)v.ve_proc - (struct proc *)namelist[1].n_value;
  253.  
  254.     (void) lseek(kmem, namelist[1].n_value, 0);
  255.     (void) read(kmem, p, size * sizeof(struct proc));
  256.  
  257.     for (nproc = 0, i=0; i<size; i++) 
  258.       if ((p[i].p_stat == SRUN) ||
  259.           (p[i].p_stat == SIDL) ||
  260.           (p[i].p_stat == SXBRK) ||
  261.           (p[i].p_stat == SSLEEP && (p[i].p_pri < PZERO) &&
  262.            (p[i].p_wchan >= first_buf) && (p[i].p_wchan < last_buf)))
  263.         nproc++;
  264.  
  265.     /* update the load average using a decay filter */
  266.     avenrun = DECAY * avenrun + nproc * (1.0 - DECAY);
  267.     *loadavg = avenrun;
  268.  
  269.     return;
  270. }
  271. #else /* not (SYSV && SYSV386) */
  272. #ifdef KVM_ROUTINES
  273. /*
  274.  *    Sun 386i Code - abstracted to see the wood for the trees
  275.  */
  276.  
  277. static struct nlist nl[2];
  278. static kvm_t *kd;
  279.  
  280. void
  281. InitLoadPoint()                    /* Sun 386i version */
  282. {
  283.     kd = kvm_open("/vmunix", NULL, NULL, O_RDONLY, "Load Widget");
  284.     if (kd == (kvm_t *)0) {
  285.     xload_error("cannot get access to kernel address space");
  286.     }
  287.     
  288.     nl[0].n_name = "avenrun";
  289.     nl[1].n_name = NULL;
  290.     
  291.     if (kvm_nlist(kd, nl) != 0) {
  292.     xload_error("cannot get name list");
  293.     }
  294.     
  295.     if (nl[0].n_value == 0) {
  296.     xload_error("Cannot find address for avenrun in the kernel\n");
  297.     }
  298. }
  299.  
  300. /* ARGSUSED */
  301. void 
  302. GetLoadPoint( w, closure, call_data )         /* Sun 386i version */
  303. Widget    w;        /* unused */
  304. XtPointer closure;    /* unused */
  305. XtPointer call_data;    /* pointer to (double) return value */
  306. {
  307.     double *loadavg = (double *)call_data;
  308.     long    temp;
  309.  
  310.     if (kvm_read(kd, nl[0].n_value, (char *)&temp, sizeof (temp)) != 
  311.     sizeof (temp)) {
  312.     xload_error("Kernel read error");
  313.     }
  314.     *loadavg = (double)temp/FSCALE;
  315. }
  316. #else /* not KVM_ROUTINES */
  317. #ifdef LOADSTUB
  318.  
  319. void InitLoadPoint()
  320. {
  321. }
  322.  
  323. /* ARGSUSED */
  324. void GetLoadPoint( w, closure, call_data )
  325.      Widget    w;        /* unused */
  326.      caddr_t    closure;    /* unused */
  327.      caddr_t    call_data;    /* pointer to (double) return value */
  328. {
  329.     *(double *)call_data = 1.0;
  330. }
  331.  
  332. #else /* not LOADSTUB */
  333.  
  334. #ifndef KMEM_FILE
  335. #define KMEM_FILE "/dev/kmem"
  336. #endif
  337.  
  338. #ifndef KERNEL_FILE
  339.  
  340. #ifdef alliant
  341. #define KERNEL_FILE "/vmunix"
  342. #endif /* alliant */
  343.  
  344. #ifdef CRAY
  345. #define KERNEL_FILE "/unicos"
  346. #endif /* CRAY */
  347.  
  348. #ifdef hpux
  349. #define KERNEL_FILE "/hp-ux"
  350. #endif /* hpux */
  351.  
  352. #ifdef macII
  353. #define KERNEL_FILE "/unix"
  354. #endif /* macII */
  355.  
  356. #ifdef umips
  357. # ifdef SYSTYPE_SYSV
  358. # define KERNEL_FILE "/unix"
  359. # else
  360. # define KERNEL_FILE "/vmunix"
  361. # endif /* SYSTYPE_SYSV */
  362. #endif /* umips */
  363.  
  364. #ifdef sequent
  365. #define KERNEL_FILE "/dynix"
  366. #endif /* sequent */
  367.  
  368. #ifdef hcx
  369. #define KERNEL_FILE "/unix"
  370. #endif /* hcx */
  371.  
  372. #ifdef MOTOROLA
  373. #if defined(SYSV) && defined(m68k)
  374. #define KERNEL_FILE "/sysV68"
  375. #endif
  376. #if defined(SYSV) && defined(m88k)
  377. #define KERNEL_FILE "/unix"
  378. #endif
  379. #ifdef SVR4
  380. #define KERNEL_FILE "/unix"
  381. #endif
  382. #endif /* MOTOROLA */
  383.  
  384. /*
  385.  * provide default for everyone else
  386.  */
  387. #ifndef KERNEL_FILE
  388. #ifdef SVR4
  389. #define KERNEL_FILE "/stand/unix"
  390. #else
  391. #ifdef SYSV
  392. #define KERNEL_FILE "/unix"
  393. #else
  394. #define KERNEL_FILE "/vmunix"
  395. #endif /* SYSV */
  396. #endif /* SVR4 */
  397. #endif /* KERNEL_FILE */
  398. #endif /* KERNEL_FILE */
  399.  
  400.  
  401. #ifndef KERNEL_LOAD_VARIABLE
  402. #    ifdef alliant
  403. #        define KERNEL_LOAD_VARIABLE "_Loadavg"
  404. #    endif /* alliant */
  405.  
  406. #    ifdef CRAY
  407. #        if defined(CRAY2) && OSMAJORVERSION == 4
  408. #            define KERNEL_LOAD_VARIABLE "avenrun"
  409. #        else
  410. #            define KERNEL_LOAD_VARIABLE "sysinfo"
  411. #            define SYSINFO
  412. #        endif /* defined(CRAY2) && OSMAJORVERSION == 4 */
  413. #    endif /* CRAY */
  414.  
  415. #    ifdef hpux
  416. #        ifdef hp9000s800
  417. #            define KERNEL_LOAD_VARIABLE "avenrun"
  418. #        endif /* hp9000s800 */
  419. #    endif /* hpux */
  420.  
  421. #    ifdef umips
  422. #        ifdef SYSTYPE_SYSV
  423. #            define KERNEL_LOAD_VARIABLE "avenrun"
  424. #        else
  425. #            define KERNEL_LOAD_VARIABLE "_avenrun"
  426. #        endif /* SYSTYPE_SYSV */
  427. #    endif /* umips */
  428.  
  429. #    ifdef sgi
  430. #     define KERNEL_LOAD_VARIABLE "avenrun"
  431. #    endif /* sgi */
  432.  
  433. #    ifdef AIXV3
  434. #        define KERNEL_LOAD_VARIABLE "sysinfo"
  435. #    endif /* AIXV3 */
  436.  
  437. #    ifdef MOTOROLA
  438. #        if defined(SYSV) && defined(m68k)
  439. #            define KERNEL_LOAD_VARIABLE "sysinfo"
  440. #        endif
  441. #        if defined(SYSV) && defined(m88k)
  442. #            define KERNEL_LOAD_VARIABLE "_sysinfo"
  443. #        endif
  444. #        ifdef SVR4
  445. #            define KERNEL_LOAD_VARIABLE "avenrun"
  446. #        endif
  447. #    endif /* MOTOROLA */
  448.  
  449. #endif /* KERNEL_LOAD_VARIABLE */
  450.  
  451. /*
  452.  * provide default for everyone else
  453.  */
  454.  
  455. #ifndef KERNEL_LOAD_VARIABLE
  456. #    ifdef USG
  457. #        define KERNEL_LOAD_VARIABLE "sysinfo"
  458. #        define SYSINFO
  459. #    else
  460. #    ifdef SVR4
  461. #        define KERNEL_LOAD_VARIABLE "avenrun"
  462. #    else
  463. #        define KERNEL_LOAD_VARIABLE "_avenrun"
  464. #    endif
  465. #    endif
  466. #endif /* KERNEL_LOAD_VARIABLE */
  467.  
  468. #ifdef macII
  469. static struct var v;
  470. static int pad[2];    /* This padding is needed if xload compiled on */
  471.             /* a/ux 1.1 is executed on a/ux 1.0, because */
  472.             /* the var structure had too much padding in 1.0, */
  473.             /* so the 1.0 kernel writes past the end of the 1.1 */
  474.             /* var structure in the uvar() call. */
  475. static struct nlist nl[2];
  476. static struct lavnum vec[3];
  477. #else /* not macII */
  478. static struct nlist namelist[] = {        /* namelist for vmunix grubbing */
  479. #define LOADAV 0
  480.     {KERNEL_LOAD_VARIABLE},
  481.     {0}
  482. };
  483. #endif /* macII */
  484.  
  485. static kmem;
  486. static long loadavg_seek;
  487.  
  488. InitLoadPoint()
  489. {
  490. #ifdef macII
  491.     extern nlist();
  492.  
  493.     int i;
  494.  
  495.     strcpy(nl[0].n_name, "avenrun");
  496.     nl[1].n_name[0] = '\0';
  497.  
  498.     kmem = open(KMEM_FILE, O_RDONLY);
  499.     if (kmem < 0) {
  500.     xload_error("cannot open", KMEM_FILE);
  501.     }
  502.  
  503.     uvar(&v);
  504.  
  505.     if (nlist( KERNEL_FILE, nl) != 0) {
  506.     xload_error("cannot get name list from", KERNEL_FILE);
  507.     }
  508.     for (i = 0; i < 2; i++) {
  509.     nl[i].n_value = (int)nl[i].n_value - v.v_kvoffset;
  510.     }
  511. #else /* not macII */
  512. #if (!defined(SVR4) || !defined(__STDC__)) && !defined(sgi) && !defined(MOTOROLA)
  513.     extern void nlist();
  514. #endif
  515.  
  516. #ifdef AIXV3
  517.     knlist( namelist, 1, sizeof(struct nlist));
  518. #else    
  519.     nlist( KERNEL_FILE, namelist);
  520. #endif
  521.     /*
  522.      * Some systems appear to set only one of these to Zero if the entry could
  523.      * not be found, I hope no_one returns Zero as a good value, or bad things
  524.      * will happen to you.  (I have a hard time believing the value will
  525.      * ever really be zero anyway).   CDP 5/17/89.
  526.      */
  527. #ifdef hcx
  528.     if (namelist[LOADAV].n_type == 0 &&
  529. #else
  530.     if (namelist[LOADAV].n_type == 0 ||
  531. #endif /* hcx */
  532.     namelist[LOADAV].n_value == 0) {
  533.     xload_error("cannot get name list from", KERNEL_FILE);
  534.     exit(-1);
  535.     }
  536.     loadavg_seek = namelist[LOADAV].n_value;
  537. #if defined(umips) && defined(SYSTYPE_SYSV)
  538.     loadavg_seek &= 0x7fffffff;
  539. #endif /* umips && SYSTYPE_SYSV */
  540. #if (defined(CRAY) && defined(SYSINFO))
  541.     loadavg_seek += ((char *) (((struct sysinfo *)NULL)->avenrun)) -
  542.     ((char *) NULL);
  543. #endif /* CRAY && SYSINFO */
  544.   
  545.     kmem = open(KMEM_FILE, O_RDONLY);
  546.     if (kmem < 0) xload_error("cannot open", KMEM_FILE);
  547. #endif /* macII else */
  548. }
  549.  
  550. /* ARGSUSED */
  551. void GetLoadPoint( w, closure, call_data )
  552.      Widget    w;        /* unused */
  553.      caddr_t    closure;    /* unused */
  554.      caddr_t    call_data;    /* pointer to (double) return value */
  555. {
  556.       double *loadavg = (double *)call_data;
  557.  
  558. #ifdef macII
  559.     lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
  560. #else
  561.     (void) lseek(kmem, loadavg_seek, 0);
  562. #endif
  563.  
  564. #if defined(sun) || defined (UTEK) || defined(sequent) || defined(alliant) || defined(SVR4) || defined(sgi) || defined(hcx)
  565.     {
  566.         long temp;
  567.         (void) read(kmem, (char *)&temp, sizeof(long));
  568.         *loadavg = (double)temp/FSCALE;
  569.     }
  570. #else /* else not sun or UTEK or sequent or alliant or SVR4 or sgi or hcx */
  571. # ifdef macII
  572.         {
  573.                 read(kmem, vec, 3*sizeof(struct lavnum));
  574.                 *loadavg = fxtod(0);
  575.         }
  576. # else /* else not macII */
  577. #  if defined(umips) || (defined(ultrix) && defined(mips))
  578.     {
  579.         fix temp;
  580.         (void) read(kmem, (char *)&temp, sizeof(fix));
  581.         *loadavg = FIX_TO_DBL(temp);
  582.     }
  583. #  else /* not umips or ultrix risc */
  584. #    ifdef AIXV3
  585.         {
  586.           struct sysinfo sysinfo_now;
  587.           struct sysinfo sysinfo_last;
  588.           static firsttime = TRUE;
  589.           static double runavg = 0.0, swpavg = 0.0;
  590.  
  591.           (void) lseek(kmem, loadavg_seek, 0);
  592.           (void) read(kmem, (char *)&sysinfo_last, sizeof(struct sysinfo));
  593.           if (firsttime)
  594.             {
  595.               *loadavg = 0.0;
  596.               firsttime = FALSE;
  597.             }
  598.           else
  599.             {
  600.               sleep(1);
  601.               (void) lseek(kmem, loadavg_seek, 0);
  602.               (void) read(kmem, (char *)&sysinfo_now, sizeof(struct sysinfo));
  603.               runavg *= 0.8; swpavg *= 0.8;
  604.               if (sysinfo_now.runocc != sysinfo_last.runocc)
  605.                 runavg += 0.2*((sysinfo_now.runque - sysinfo_last.runque - 1)
  606.                           /(double)(sysinfo_now.runocc - sysinfo_last.runocc));
  607.               if (sysinfo_now.swpocc != sysinfo_last.swpocc)
  608.                 swpavg += 0.2*((sysinfo_now.swpque - sysinfo_last.swpque)
  609.                           /(double)(sysinfo_now.swpocc - sysinfo_last.swpocc));
  610.               *loadavg = runavg + swpavg;
  611.               sysinfo_last = sysinfo_now;
  612.             }
  613.           /* otherwise we leave load alone. */
  614.         }
  615. #    else /* not AIXV3 */
  616. #      if defined(MOTOROLA) && defined(SYSV)
  617.     {
  618.         static int init = 0;
  619.         static kmem;
  620.         static long loadavg_seek;
  621.         static xload_error();
  622.  
  623. #define CEXP    0.25            /* Constant used for load averaging */
  624.  
  625.         struct sysinfo sysinfod;
  626.         static double oldloadavg;
  627.         static double cexp = CEXP;
  628.         static long sv_rq, sv_oc;   /* save old values */
  629.         double rq, oc;              /* amount values have changed */
  630.  
  631.         if (!init)
  632.         {
  633.             if (nlist(KERNEL_FILE,namelist) == -1)
  634.             {
  635.                 perror("xload: nlist()");
  636.                 xload_error("cannot get name list from", KERNEL_FILE);
  637.             }
  638.             loadavg_seek = namelist[0].n_value;
  639.  
  640.             kmem = open(KMEM_FILE, O_RDONLY);
  641.             if (kmem < 0)
  642.             {
  643.                 perror("xload: open()");
  644.                 xload_error("cannot open", KMEM_FILE);
  645.             }
  646.         }
  647.  
  648.         lseek(kmem, loadavg_seek, 0);
  649.         if (read(kmem, &sysinfod, (int) sizeof (struct sysinfo)) == -1)
  650.         {
  651.              perror("xload: read() SYSINFONL");
  652.              xload_error("read failed from", KMEM_FILE);
  653.         }
  654.  
  655.         if (!init)
  656.         {
  657.             init = 1;
  658.             sv_rq = sysinfod.runque;
  659.             sv_oc = sysinfod.runocc;
  660.             oldloadavg = *loadavg = 0.0;
  661.             return;
  662.         }
  663.         /*
  664.          * calculate the amount the values have
  665.          * changed since last update
  666.          */
  667.         rq = (double) sysinfod.runque - sv_rq;
  668.         oc = (double) sysinfod.runocc - sv_oc;
  669.  
  670.         /*
  671.          * save old values for next time
  672.          */
  673.         sv_rq = sysinfod.runque;
  674.         sv_oc = sysinfod.runocc;
  675.  
  676.         if (oc == 0.0)          /* avoid divide by zero  */
  677.         {
  678.                 *loadavg = (1.0 - cexp) * oldloadavg;
  679.  
  680.         }
  681.         else
  682.         {
  683.                 *loadavg = ((1.0 - cexp) * oldloadavg) ((rq / oc) * cexp);
  684.         }
  685.         oldloadavg = *loadavg;
  686.     }
  687. #      else /* not MOTOROLA */
  688. #     if defined(sony) && OSMAJORVERSION == 4
  689. #      ifdef mips
  690.     {
  691.         fix temp;
  692.         (void) read(kmem, (char *)&temp, sizeof(fix));
  693.         *loadavg = FIX_TO_DBL(temp);
  694.     }
  695. #      else /* not mips */
  696.     {
  697.         long temp;
  698.         (void) read(kmem, (char *)&temp, sizeof(long));
  699.         *loadavg = (double)temp/FSCALE;
  700.     }
  701. #      endif /* mips */
  702. #     else /* not sony NEWSOS4 */
  703.     (void) read(kmem, (char *)loadavg, sizeof(double));
  704. #        endif /* sony NEWOS4 */
  705. #      endif /* MOTOROLA else */
  706. #    endif /* AIXV3 else */
  707. #  endif /* umips else */
  708. # endif /* macII else */
  709. #endif /* sun else */
  710.     return;
  711. }
  712. #endif /* LOADSTUB else */
  713. #endif /* KVM_ROUTINES else */
  714. #endif /* SYSV && SYSV386 else */
  715.  
  716. static xload_error(str1, str2)
  717. char *str1, *str2;
  718. {
  719.     (void) fprintf(stderr,"xload: %s %s\n", str1, str2);
  720.     exit(-1);
  721. }
  722.  
  723. #endif /* apollo else */
  724.  
  725.